# -*- coding:utf-8 -*-
# @Time : 21-9-27 下午2:21 
# @Author : zdy
# @File : PortManager.py
# desc: 天平
import binascii

import serial.tools.list_ports
from serial import PARITY_NONE, PARITY_EVEN, PARITY_ODD, STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO
import os, threading, time
from importQT import *

def HexStr2Unicode(Hex_Str):
    """*Function: HexStr2Unicode
     *Description：  16
     进制字符串转换为Unicode字符串
     *Input: Hex_Str
     16
     进制字符串
     *Return: Unicde_Str
     Unicode字符串
     *Others:"""
    str1 = ""
    for i in range(0, len(Hex_Str) // 4):
        chr(int(Hex_Str[i * 4:i * 4 + 4], 16))
        str1 += chr(int(Hex_Str[i * 4:i * 4 + 4], 16))

    return str1

class PortManager(QObject):
    sigReceive = pyqtSignal(str)  # 原始数据
    sigSendWeight = pyqtSignal(float)  # 发送质量

    def __init__(self, parent=None):
        super(PortManager, self).__init__(parent)
        self.serialPort = serial.Serial()
        self.portName = "/dev/ttyUSB1"
        self.baudRate = 1200
        self.parity = PARITY_NONE  # None无校验
        self.dataBits = 8
        self.stopBits = STOPBITS_ONE  # 1位停止位，对应天平调试界面选中index
        self.threadReceiveCom = None

    def init(self, path):
        """
        设置天平参数，开启数据采集后台线程，打开天平串口
        :return: 天平打开状态
        """
        self.loadParam(path)
        self.setParams()
        self.threadReceiveCom = threading.Thread(target=self.data_receive)
        self.threadReceiveCom.setDaemon(True)  # 后台线程
        self.threadReceiveCom.start()

    def data_receive(self):
        '''接收数据'''
        while True:
            time.sleep(0.1)
            if not self.serialPort.is_open:
                continue
            try:
                num = self.serialPort.inWaiting()
            except:
                print("串口waiting异常")
                return None
            if num > 0:
                try:
                    data = self.serialPort.readline() # bytes
                    # msg = data.decode("utf-8",errors="ignore")
                    msg = data.decode("ASCII") #国产天平
                except Exception as ex:
                    continue
                self.sigReceive.emit(msg.strip(os.linesep))
                if ("K" in msg and not ("*" in msg) and not ("-" in msg)) or ("g" in msg):
                    index = -1
                    try:
                        index = msg.index(".")
                    except:
                        continue
                    start = 0
                    listmsg = list(msg)
                    for i in range(index-1, -1, -1):
                        if listmsg[i].isdigit():
                            start = i
                        else:
                            break
                    value = float(msg[start:index + 5])
                    if value > 0.001:
                        self.sigSendWeight.emit(value)

    def open(self):
        try:
            if self.serialPort.isOpen():
                self.serialPort.close()
            self.serialPort.open()
            if self.serialPort.isOpen():
                self.serialPort.flushInput()
                return True
            else:
                return False
        except Exception as ex:
            return str(ex)

    def close(self):
        """关闭天平串口连接"""
        try:
            if self.serialPort.isOpen():
                self.serialPort.close()
            return True
        except:
            return False

    def loadParam(self, path):
        """
        读取配置文件，更新天平参数
        :param path: 文件地址
        :return: 若文件不存在、数据异常，则返回False
        """
        if os.path.exists(path):
            params = []
            with open(path, "r") as f:  # 以读方式打开，只能读文件 ， 如果文件不存在，会发生异常
                params = f.readlines()
            if len(params) == 5:
                try:
                    self.portName = params[0].strip(os.linesep)
                    self.baudRate = int(params[1].strip(os.linesep))
                    self.parity = str(params[2].strip(os.linesep))
                    self.dataBits = int(params[3].strip(os.linesep))
                    self.stopBits = int(params[4].strip(os.linesep))
                except:
                    return False
                return True
        return False

    def saveParam(self, path):
        """
        保存天平参数：以写方式打开，只能写文件， 如果文件不存在，创建该文件;如果文件已存在，先清空，再打开文件
        :param path:文件地址
        :return:
        """
        with open(path, "w") as f:
            params = [self.portName + os.linesep, str(self.baudRate) + os.linesep, str(self.parity) + os.linesep,
                      str(self.dataBits) + os.linesep, str(self.stopBits) + os.linesep]
            f.writelines(params)

    def setParams(self):
        """更新天平串口设置"""
        self.serialPort.port = self.portName
        self.serialPort.baudrate = self.baudRate
        self.serialPort.bytesize = self.dataBits
        self.serialPort.stopbits = self.stopBits
        self.serialPort.parity = self.parity
        self.serialPort.timeout = 0.5

    def isOpened(self):
        """返回天平串口打开状态"""
        return self.serialPort.is_open


portManager = PortManager()


